home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2002 #11 / Amiga Plus CD - 2002 - No. 11.iso / Tools / Development / Feelin021015 / Examples / Class3.c < prev    next >
C/C++ Source or Header  |  2002-10-28  |  8KB  |  273 lines

  1. #include <stdio.h>
  2.  
  3. #include <clib/exec_protos.h>
  4. #include <clib/dos_protos.h>
  5. #include <clib/graphics_protos.h>
  6. #include <clib/feelin_protos.h>
  7.  
  8. #include <libraries/feelin.h>
  9.  
  10. struct FeelinBase *FeelinBase;
  11.  
  12. ///OBJ
  13. // This is the instance data for our custom class.
  14.  
  15. struct LocalObjectData {
  16.   WORD x,y, sx,sy;
  17. };
  18. //+
  19.  
  20. /// mAskMinMax
  21. /*
  22.    Area.AskMinMax() will be called before the window is opened. We need  to
  23.    tell Feelin the minimum and maximum size of our object.
  24.  
  25.    When you are the first receiving  the  method  the  fields  _minw()  and
  26.    _minh() are set to zero and the fields _maxw() and _maxh() to FV_MAXMAX.
  27.    We can add values to _minw() and _minh() or set _maxw() and  _maxh()  if
  28.    we need to. Then we pass the method to our superclass.
  29.  
  30.    When the method  reaches  Area  class  these  values  will  be  adjusted
  31.    according to FA_MinXxx, FA_FixedXxx and FA_FixXxx attributes.
  32. */
  33.  
  34. ULONG SAVEDS mAskMinMax(struct FeelinClass *psClass,APTR Obj,ULONG *pnArgs)
  35. {
  36.    _minw(Obj) += 100; _minh(Obj) += 040;
  37.    _maxw(Obj)  = 500; _maxh(Obj)  = 300;
  38.  
  39.    return F_SuperDoA(psClass,Obj,FM_AskMinMax,pnArgs);
  40. }
  41. //+
  42. /// mDraw
  43. /*
  44.    Draw method is called whenever Feelin feels (obviously  ;-))  we  should
  45.    render  our object. This usually happens after layout is finished. Note:
  46.    You may only render within the rectangle _mleft(),  _mtop(),  _mwidth(),
  47.    _mheight().
  48. */
  49. ULONG SAVEDS mDraw(struct FeelinClass *psClass,APTR Obj,struct LocalObjectData *psLOD,struct FS_Draw *psDraw)
  50. {
  51.    APTR rp;
  52.  
  53. /*
  54.    Let our superclass draw itself first, Area class  would  e.g.  draw  the
  55.    frame and clear the whole region. What it does exactly depends on flags.
  56. */
  57.  
  58.    F_SuperDoA(psClass,Obj,FM_Draw,(ULONG *)psDraw);
  59.  
  60. /*
  61.    IF FF_Draw_Object isn't set, we shouldn't  draw  anything.  Feelin  just
  62.    wanted to update the frame or something like that.
  63. */
  64.  
  65.    rp = _rp(Obj);
  66.  
  67.    if (psDraw->Flags & FF_Draw_Update) // called from our input method
  68.    {
  69.       if (psLOD->sx || psLOD->sy)
  70.       {
  71.          _BPen(_pen(Obj,FV_Pen_Shine));
  72.          ScrollRaster(rp,psLOD->sx,psLOD->sy,_mx(Obj),_my(Obj),_mx2(Obj),_my2(Obj));
  73.          _BPen(_pen(Obj,FV_Pen_Dark));
  74.          psLOD->sx = NULL;
  75.          psLOD->sy = NULL;
  76.       }
  77.       else
  78.       {
  79.          _APen(_pen(Obj,FV_Pen_Shadow));
  80.          _Plot(psLOD->x,psLOD->y);
  81.       }
  82.    }
  83.    else if (psDraw->Flags & FF_Draw_Object)
  84.    {
  85.       _APen(_pen(Obj,FV_Pen_Shine));
  86.       _Boxf(_mx(Obj),_my(Obj),_mx2(Obj),_my2(Obj));
  87.    }
  88.  
  89.    return NULL;
  90. }
  91. //+
  92. /// mActive
  93. /*
  94.    Area class always creates an EventHandler  structure  in  case  of  some
  95.    inputmodes.  As  we handle events instead of Area class we can use it as
  96.    we want. It will save us some allocations ;-)
  97.  
  98.    Using F_ModifyHandler() to modify IDCMP flags it's a piece  of  cake  to
  99.    request IDCMP events.
  100. */
  101.  
  102. ULONG SAVEDS mActive(struct FeelinClass *psClass,APTR Obj,BOOL bState)
  103. {
  104.    if (bState)
  105.    {
  106.       F_Do(Obj,FM_ModifyHandler,IDCMP_RAWKEY | IDCMP_MOUSEBUTTONS,NULL);
  107.    }
  108.    else
  109.    {
  110.       F_Do(Obj,FM_ModifyHandler,NULL,IDCMP_RAWKEY | IDCMP_MOUSEBUTTONS);
  111.    }
  112.  
  113.    return F_SuperDoA(psClass,Obj,bState ? FM_Active : FM_Inactive,NULL);
  114. }
  115. //+
  116. ///mHandleEvent
  117. /*
  118. in mSetup() we said that we want get a  message  if  mousebuttons  or  keys
  119. pressed so we have to define the input-handler
  120.  
  121. Note :
  122.  
  123.    This is really a good example, because it  shows  how  to  use  critical
  124.    events carefully:
  125.  
  126.    IDCMP_MOUSEMOVE is only needed when left-mousebutton is pressed,  so  we
  127.    dont  request  this  until  we  get  a  SELECTDOWN-message and we reject
  128.    IDCMP_MOUSEMOVE immeditly after we get a SELECTUP-message
  129. */
  130.  
  131. ULONG SAVEDS mHandleEvent(APTR Obj, struct LocalObjectData *psLOD, struct FS_HandleEvent *psHE)
  132. {
  133.    #define _between(a,x,b) ((x) >= (a) && (x) <= (b))
  134.    #define _isinobject(x,y) (_between(_mx(Obj),(x),_mx(Obj) + _mw(Obj) - 1) && _between(_my(Obj),(y),_my(Obj) + _mh(Obj) - 1))
  135.  
  136. /*
  137. Note on Arrows handling :
  138.  
  139. If you don't handle arrows return NIL, this will  allow  Window  object  to
  140. cycle   through  its  chain  using  arrows  instead  of  tabulations  (more
  141. confortable hu ?), else return your object. Currently, result is only check
  142. against NIL, but this may change in future, so return your object.
  143. */
  144.  
  145.    if (psHE->Key != FV_Key_None)
  146.    {
  147.       switch (psHE->Key)
  148.       {
  149.          case FV_Key_Left:  psLOD->sx = -1; break;
  150.          case FV_Key_Right: psLOD->sx =  1; break;
  151.          case FV_Key_Up:    psLOD->sy = -1; break;
  152.          case FV_Key_Down:  psLOD->sy =  1; break;
  153.          default:       return NULL;
  154.       }
  155.  
  156.       F_Draw(Obj,FF_Draw_Update);
  157.  
  158.       return ((ULONG)Obj); // Forbid arrow cycling, because *WE* handle key events.
  159.    }
  160.    else if (psHE->Msg->Class == IDCMP_MOUSEBUTTONS)
  161.    {
  162.       if (psHE->Msg->Code == SELECTDOWN)
  163.       {
  164.          if (_isinobject(psHE->Msg->MouseX,psHE->Msg->MouseY))
  165.          {
  166.             psLOD->x = psHE->Msg->MouseX;
  167.             psLOD->y = psHE->Msg->MouseY;
  168.             F_Draw(Obj,FF_Draw_Update);
  169.             // Only request IDCMP_MOUSEMOVE if we realy need it
  170.             F_Do(Obj,FM_ModifyHandler,IDCMP_MOUSEMOVE,NULL);
  171.          }
  172.       }
  173.       else
  174.       {
  175.          // Reject IDCMP_MOUSEMOVE because lmb is no longer pressed
  176.          F_Do(Obj,FM_ModifyHandler,NULL,IDCMP_MOUSEMOVE);
  177.       }
  178.    }
  179.    else if (psHE->Msg->Class == IDCMP_MOUSEMOVE)
  180.    {
  181.       if (_isinobject(psHE->Msg->MouseX,psHE->Msg->MouseY))
  182.       {
  183.          psLOD->x = psHE->Msg->MouseX;
  184.          psLOD->y = psHE->Msg->MouseY;
  185.          F_Draw(Obj,FF_Draw_Update);
  186.       }
  187.    }
  188.  
  189.    return NULL;
  190. }
  191. //+
  192. ///myDispatcher
  193. ULONG ASM SAVEDS myDispatcher(REG_A2 struct FeelinClass  *psClass,REG_A0 APTR Obj,REG_D0 ULONG nMethod,REG_A1 ULONG *pnArgs)
  194. {
  195.    struct LocalObjectData *psLOD;
  196.  
  197.    psLOD = INST_DATA(psClass,Obj);
  198.  
  199. /*
  200. Here comes the dispatcher for our custom class. Unknown/unused methods  are
  201. passed to the superclass immediately.
  202. */
  203.  
  204.    switch (nMethod)
  205.    {
  206.       case FM_AskMinMax:    return mAskMinMax   (psClass,Obj,pnArgs);
  207.       case FM_Draw:         return mDraw        (psClass,Obj,psLOD,(struct FS_Draw *)pnArgs);
  208.       case FM_HandleEvent:  return mHandleEvent (Obj,psLOD,(struct FS_HandleEvent *)pnArgs);
  209.       case FM_Active:       return mActive      (psClass,Obj,TRUE);
  210.       case FM_Inactive:     return mActive      (psClass,Obj,FALSE);
  211.       default:              return F_SuperDoA   (psClass,Obj,nMethod,pnArgs);
  212.    }
  213. }
  214. //+
  215.  
  216. /// Main
  217. void main()
  218. {
  219.    APTR c,w,myobj;
  220.    struct FeelinClass *psFCC;
  221.  
  222.    if (FeelinBase = (struct FeelinBase *)OpenLibrary("feelin.library",FV_VERSION))
  223.    {
  224. /*
  225. Create the new custom class with a call to F_CreateClass().
  226.  
  227. This function returns a feelinClass structure. You  must  use  class.id  to
  228. create  instance  of  your  custom  class.  This  ID  is unique and made by
  229. F_CreateClass() when ID is NIL.
  230. */
  231.  
  232.       if (psFCC = F_CreateClass(FA_SuperID,     FC_Area,
  233.                                 FA_DataSize,    sizeof (struct LocalObjectData),
  234.                                 FA_Dispatcher,  myDispatcher,
  235.                                 TAG_DONE))
  236.       {
  237.          c = ClientObject,
  238.             Child, w = WindowObject, FA_Window_Title, "A rather complex custom class",
  239.                Child, VGroup,
  240.                   Child, TextObject, FA_FixedHeight,TRUE, DontChain, TextFrame, TextBack, FA_Text, "`c`iPaint `nwith `bmouse`n,\n`iScroll `nwith `bcursor keys`n.", End,
  241.                   Child, myobj = F_NewObj(psFCC->ID, TextFrame, TAG_DONE),
  242.                End,
  243.  
  244.                FA_Window_ActiveObject, myobj, // Safe here
  245.             End,
  246.          End;
  247.  
  248.          if (c)
  249.          {
  250.             F_Do(w,FM_Notify,FA_Window_CloseRequest,TRUE, c,2,FM_Client_ReturnID,FV_Client_Quit);
  251.             F_Set(w,FA_Window_Open,TRUE);
  252.  
  253.             F_DoA(c,FM_Client_Run,NULL);
  254.  
  255.             F_DisposeObj(c);
  256.          }
  257.  
  258.          F_RemoveClass(psFCC);
  259.       }
  260.       else
  261.       {
  262.          Printf("Could not create custom class.\n");
  263.       }
  264.  
  265.       CloseLibrary((struct Library *)FeelinBase);
  266.    }
  267.    else
  268.    {
  269.       Printf("Failed to open feelin.library\n");
  270.    }
  271. }
  272. //+
  273.